/*
 * Object   : CHelper
 * Type     : Backend
 *
 * Narrator : Kamran H. Khan 
 * Email    : KAMRANHK@gmail.com
 * 
 * Copyleft : Attribution - CreativeCommons http://creativecommons.org/licenses/by-nc/3.0/
 *            This software is provided 'as-is', without any express or implied warranty.
 *            In no event will the author(s) be held liable for any damages arising from
 *            the use of this software.
 * 
 *            Permission is granted to anyone to use this software for any purpose,
 *            including commercial applications, and to alter it and redistribute it
 *            freely, subject to the following restrictions:
 * 
 *            1. The origin of this software must not be misrepresented; you must not
 *            claim that you wrote the original software. If you use this software
 *            in a product, an acknowledgment in the product documentation would be
 *            appreciated but is not required.
 * 
 *            2. Altered source versions must be plainly marked as such, and must not
 *            be misrepresented as being the original software.
 * 
 *            3. This notice may not be removed or altered from any source distribution.
 *  * Description: 
 * Helps us.
 * 
 * Revision History:
 * 
 * Date(MMM/dd/yy)      Owner           Description
 * ----------------------------------------------------------------------------------------------------------------------------------------------
 * Oct/24/08            Kamran H. Khan  Added skeleton code
 * Oct/25/08            Kamran H. Khan  Added methods
 *                                          - Log()
 *                                          - Error()
 *  
 * 
 * 
 * 
*/


using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace Maxima.Help
{
    public class CHelper
    {
        /// <summary>
        /// Logs the specified STR MSG.
        /// </summary>
        /// <param name="strMsg">The STR MSG.</param>
        public static void Log(string strMsg)
        {
            //txtStatus.Text += strMsg;
            string strLogFilePath = Application.ExecutablePath.ToString().ToLower();
            string strLogFilename = "MySim9-Log-" + DateTime.Now.Day.ToString().PadLeft(2, '0') + DateTime.Now.Month.ToString().PadLeft(2, '0') + ".log";
            strLogFilePath = strLogFilePath.Replace("mysim9.exe", strLogFilename);

            using (System.IO.StreamWriter theWriter = new System.IO.StreamWriter(strLogFilePath, true, Encoding.UTF8))
            {
                string strStamp = DateTime.Now.ToString("yy/MM/dd HH:mm:ss.fff");
                strMsg = strStamp + "\t| " + strMsg;
                theWriter.WriteLine(strMsg);
            }
        }

        /// <summary>
        /// Errors the specified STR MSG.
        /// </summary>
        /// <param name="strMsg">The STR MSG.</param>
        private void Error(string strMsg)
        {

            //txtStatus.Text += "ERR: " + strMsg;
        }

        /// <summary>
        /// Strings to hex.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <returns></returns>
        public static string StringToHex(string strData)
        {
            string hex = string.Empty;
            foreach (char c in strData)
            {
                int tmp = c;
                hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
            }
            return hex;
        }

        /// <summary>
        /// Hexes to string.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <returns></returns>
        public static string HexToString(string strData)
        {
            string str1 = string.Empty;
            string str2 = string.Empty;

            while (strData.Length > 0)
            {
                str1 = System.Convert.ToChar(System.Convert.ToUInt32(strData.Substring(0, 2), 16)).ToString();
                str2 = str2 + str1;
                strData = strData.Substring(2, strData.Length - 2);
            }

            return str2;
        }

        /// <summary>
        /// Strings to binary.
        /// </summary>
        /// <param name="theString">The string.</param>
        /// <param name="desiredLength">Length of the desired.</param>
        /// <returns></returns>
        public static byte[] StringToBinary(string theString, int desiredLength)
        {
            ASCIIEncoding encoder = new ASCIIEncoding();
            byte[] byteStream = new byte[(uint)desiredLength];
            encoder.GetBytes(theString, 0, (theString.Length <= desiredLength) ? theString.Length : desiredLength, byteStream, 0);
            return byteStream;
        }

        /// <summary>
        /// Gets the bytes from binary string.
        /// </summary>
        /// <param name="binary">The binary.</param>
        /// <param name="bitsPerByte">The bits per byte.</param>
        /// <returns></returns>
        public static byte[] GetBytesFromBinaryString(string binary, int bitsPerByte)
        {
            List<byte> list = new List<byte>();
            for (int i = 0; i < binary.Length; i += bitsPerByte)
            {
                string t = binary.Substring(i, bitsPerByte);

                list.Add(Convert.ToByte(t, 2));
            }
            return list.ToArray();
        }

        /// <summary>
        /// Binaries to string.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <returns></returns>
        public static string BinaryToString(string strData)
        {
            string str = string.Empty;
            foreach (char c in strData)
            {
                int tmp = c;
                str += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
            }
            return str;
        }

        /// <summary>
        /// Strings to binary.
        /// </summary>
        /// <param name="nLength">Length of the n.</param>
        /// <returns></returns>
        public static string StringToBinary(int nLength)
        {
            string str = Convert.ToString(nLength, 2);

            return str;
        }

        /// <summary>
        /// Toes the meta.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <returns></returns>
        public static string ToMeta(string strData)
        {
            string str = string.Empty;
            str = Convert.ToBase64String(StringToBinary(strData, strData.Length));
            return str;
        }

        /// <summary>
        /// Toes the meta.
        /// </summary>
        /// <param name="nLength">Length of the n.</param>
        /// <returns></returns>
        public static string ToMeta(int nLength)
        {
            string str = string.Empty;
            str = Convert.ToChar(nLength).ToString();
            return str;
        }


        /// <summary>
        /// Gets the length of the meta.
        /// </summary>
        /// <param name="nDataLength">Length of the n data.</param>
        /// <returns></returns>
        private static string GetMetaLength(int nDataLength)
        {
            //Steps to calculate the meta length in characters
            //STEP 1: Get the div part. Divide data length by 256 - //int nPartDiv = nDataLength / 256;
            //STEP 2: Get the Modulus part. Take modulus of Data length by 256 - //int nPartMod = nDataLength % 256;
            //STEP 3: Convert into characters, concat and return. //Convert.ToChar(nPartDiv).ToString() + Convert.ToChar(nPartMod).ToString();

            string strLengthInChars = string.Empty;
            strLengthInChars = Convert.ToChar((nDataLength / 256)).ToString() + Convert.ToChar((nDataLength % 256)).ToString();
            List<string> lst = new List<string>();

            return strLengthInChars;
        }

        private const int DecimalRadix = 10;
        private const int MaxBit = 32;
        private static char[] _hexChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        private static int[] _hexValues = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
        /// <summary>
        /// Bases to decimal.
        /// </summary>
        /// <param name="completeHex">The complete hex.</param>
        /// <param name="radix">The radix.</param>
        /// <returns></returns>
        public static int BaseToDecimal(string completeHex, int radix)
        {
            int value = 0;
            int product = 1;
            for (int i = completeHex.Length - 1; i >= 0; i--, product = product * radix)
            {
                char hex = completeHex[i];
                int hexValue = -1;
                for (int j = 0; j < _hexChars.Length - 1; j++)
                {
                    if (_hexChars[j] == hex)
                    {
                        hexValue = _hexValues[j];
                        break;
                    }
                }
                value += (hexValue * product);
            }
            return value;
        }

        /// <summary>
        /// Decimals to base.
        /// </summary>
        /// <param name="decimalValue">The decimal value.</param>
        /// <param name="radix">The radix.</param>
        /// <returns></returns>
        public static string DecimalToBase(int decimalValue, int radix)
        {
            string completeHex = "";
            int[] remainders = new int[MaxBit];
            int maxBit = MaxBit;
            for (; decimalValue > 0; decimalValue = decimalValue / radix)
            {
                maxBit = maxBit - 1;
                remainders[maxBit] = decimalValue % radix;
            }
            for (int i = 0; i < remainders.Length; i++)
            {
                int value = remainders[i];
                if (value >= DecimalRadix)
                {
                    completeHex += _hexChars[value % DecimalRadix];
                }
                else
                {
                    completeHex += value;
                }
            }
            completeHex = completeHex.TrimStart(new char[] { '0' });
            return completeHex;

        }

        internal static void TestConversions()
        {
            ConvertBinary1();
            string str = "64";
            int nBitsPerByte = 8;//
            string strBinary = Convert.ToString(64, 2);

            byte[] BinaryBytes = GetBytesFromBinaryString(strBinary, nBitsPerByte);
            byte[] BinaryBytes2 = System.Text.ASCIIEncoding.ASCII.GetBytes(str);
            StringToBinary(str, 2);
        }

        private static void ConvertBinary1()
        {
            string strData = "64";

            //string str1 = GetMetaLength(strData.Length);
            //string str2 = "00000100";//decimal 4
            
            //byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(strData);

            ////byte[] bytes = { 10, 255, 2, 78 };	// Sample data.
            
            //string str3 = string.Empty;
            //Array.ForEach<byte>(
            //   bytes,
            //   delegate(byte b)
            //   {
            //       for (byte c = 1; c != 0; b <<= 1, c <<= 1)
            //       {

            //           if ((b & 0x80) == 0)
            //               str3 += "0";
            //           else
            //               str3 += "1";
            //       }
            //   });

            string tmpString2 = "64";
            //for (int i = 0; i < 256; i++) tmpString2 += (char)i; //build str
            char[] tmp = Convert2CharArray(tmpString2);
            bool t = true;

            
            for (int i = 0; i < 256; i++) t = t && (tmp[i] == ((char)i));
            if (t) MessageBox.Show("yes");

            t = true;
            
            string tmpstr = Convert2string(tmp); //translate back.

            for (int i = 0; i < tmpstr.Length; i++) 
                t = t && (tmpstr[i] == tmp[i]);
            if (t) MessageBox.Show("yes done");

        }

        public static char[] Convert2CharArray(string str)
        {
            char[] ret = new char[str.Length];
            for (int i = 0; i < str.Length; i++) ret[i] = str[i];
            return ret;
        }

        public static string Convert2string(char[] charArray)
        {
            string ret = "";
            for (int i = 0; i < charArray.Length; i++) ret += charArray[i];
            return ret;
        }

        /// <summary>
        // 168-bit (three-key) 3DES (Triple-DES) encrypt a single 8-byte block (ECB mode)
        // plain-text should be 8-bytes, key should be 24 bytes.
        /// </summary>
        /// <see cref="http://www.chilkatsoft.com/p/p_330.asp"/>
        /// <param name="plainText"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public byte[] To3DESEncryptOneBlock(byte[] plainText, byte[] key)
        {
            // Create a new 3DES key.
            System.Security.Cryptography.TripleDESCryptoServiceProvider des = new System.Security.Cryptography.TripleDESCryptoServiceProvider();

            // Set the KeySize = 192 for 168-bit DES encryption.
            // The msb of each byte is a parity bit, so the key length is actually 168 bits.
            des.KeySize = 192;
            des.Key = key;
            des.Mode = System.Security.Cryptography.CipherMode.ECB;
            des.Padding = System.Security.Cryptography.PaddingMode.None;

            System.Security.Cryptography.ICryptoTransform ic = des.CreateEncryptor();

            byte[] enc = ic.TransformFinalBlock(plainText, 0, 8);

            return enc;
        }


        internal static void Log(string strObject_Method, string strMsg)
        {
            string strSeparator = "\t|";
            string str = strObject_Method + strSeparator + strMsg ;
            Log(str);
        }

        internal static void Log(string strObject_Method, string strMsg, string strArguments)
        {
            string strSeparator = "\t|";
            string str = strObject_Method + strSeparator + strMsg + ": ["+ strArguments + "]";
            Log(str);
        }
    }
}
